package com.lemon.rule.express.instruction;

import java.util.Stack;

import com.lemon.rule.express.ExportItem;
import com.lemon.rule.express.ExpressRunner;
import com.lemon.rule.express.InstructionSet;
import com.lemon.rule.express.instruction.detail.InstructionGoToWithCondition;
import com.lemon.rule.express.instruction.detail.InstructionGoToWithNotNull;
import com.lemon.rule.express.instruction.detail.InstructionOperator;
import com.lemon.rule.express.instruction.detail.InstructionReturn;
import com.lemon.rule.express.instruction.op.OperatorBase;
import com.lemon.rule.express.parse.ExpressNode;

class OperatorInstructionFactory extends InstructionFactory {
    public boolean createInstruction(ExpressRunner aCompile, InstructionSet result, Stack<ForRelBreakContinue> forStack, ExpressNode node, boolean isRoot) throws Exception {
        boolean returnVal = false;
        ExpressNode[] children = node.getChildren();
        int[] finishPoint = new int[children.length];
        for (int i = 0; i < children.length; i++) {
            ExpressNode tmpNode = children[i];
            boolean tmpHas = aCompile.createInstructionSetPrivate(result, forStack, tmpNode, false);
            returnVal = returnVal || tmpHas;
            finishPoint[i] = result.getCurrentPoint();
        }

        if (node.isTypeEqualsOrChild("return")) {
            result.addInstruction(new InstructionReturn(children.length > 0));
        } else {
            OperatorBase op = aCompile.getOperatorFactory().newInstance(node);
            result.addInstruction(new InstructionOperator(op, children.length));
            if (node.isTypeEqualsOrChild("&&") && aCompile.isShortCircuit()) {
                result.insertInstruction(finishPoint[0] + 1, new InstructionGoToWithCondition(false, result.getCurrentPoint() - finishPoint[0] + 1, false));
            } else if (node.isTypeEqualsOrChild("||") && aCompile.isShortCircuit()) {
                result.insertInstruction(finishPoint[0] + 1, new InstructionGoToWithCondition(true, result.getCurrentPoint() - finishPoint[0] + 1, false));
            } else if (node.isTypeEqualsOrChild("nor")) {
                result.insertInstruction(finishPoint[0] + 1, new InstructionGoToWithNotNull(result.getCurrentPoint() - finishPoint[0] + 1, false));
            } else if (node.isTypeEqualsOrChild("def") || node.isTypeEqualsOrChild("alias")) {
                returnVal = true;
            } else if (node.isTypeEqualsOrChild("exportDef")) {
                //��Ӷ���ı�������
                result.addExportDef(new ExportItem(children[1].toString(), ExportItem.TYPE_DEF, "��û��ʵ��"));
            } else if (node.isTypeEqualsOrChild("exportAlias")) {
                result.addExportDef(new ExportItem(children[0].toString(), ExportItem.TYPE_ALIAS, "��û��ʵ��"));
            }
        }
        return returnVal;
    }
}
